﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Binalyse.Memory;
namespace Binalyse
{
    public class MemalyseDocument
    {
        public string ModuleName { get; set; }
        public IntPtr ModuleAddress { get; set; }
        public uint ProcessId { get; set; }
        public string ProcessName { get; set; }
        public List<PESection> Sections { get; set; }
        public List<Heap> Heaps { get; set; }
        private Version verSystem = Environment.OSVersion.Version;
        private bool bIsWin64 = Environment.Is64BitOperatingSystem;
        private int nMajorDocVersion = 1;
        private int nMinorDocVersion = 0;

        public string Title
        {
            get 
            {
                if (ProcessId == 0) return "无标题";
                else return string.Format("[PID:{0},PNAME:{1},MOD:{2}]", ProcessId, ProcessName, ModuleName);
            }
        }
        public bool AnalyseMemory(uint pid, string pname, IntPtr modAddr, string modName)
        {
            IntPtr hProcess = Win32API.OpenProcess(Win32API.PROCESS_QUERY_INFORMATION | Win32API.PROCESS_VM_WRITE | Win32API.PROCESS_VM_READ, false, pid);
            if (hProcess == IntPtr.Zero)
            {
                MessageBox.Show(string.Format("打开进程失败,错误代码{0}", Win32API.GetLastError()), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            List<PESection> sections = Win32API.GetPESections(hProcess, modAddr, Win32API.PAGE_READWRITE);
            List<Heap> heaps = Win32API.GetHeapInformation(hProcess);
            foreach (Heap h in heaps)
            {
                Win32API.AnalyseHeapBlocks(h);
            }
            Win32API.CloseHandle(hProcess);

            if (sections == null) return false;

            Sections = sections;
            Heaps = heaps;
            ModuleName = modName;
            ModuleAddress = modAddr;
            ProcessId = pid;
            ProcessName = pname;

            return true;
        }
        public bool Save(string strPathname)
        {
            try
            {
                using (StreamWriter sw = new StreamWriter(strPathname))
                {
                    sw.Write("MEMDOC");
                    sw.Write(nMajorDocVersion);
                    sw.Write(nMinorDocVersion);
                    sw.Write("OS");
                    sw.Write(bIsWin64);
                    sw.Write(verSystem.Major);
                    sw.Write(verSystem.Minor);
                    sw.Write("GLOBAL");
                    //全局内存
                    if (Sections != null)
                    {
                        sw.Write(Sections.Count);
                        foreach (PESection peSec in Sections)
                        {
                            sw.Write(peSec.Address.ToInt32());
                            sw.Write(peSec.Flag);
                            sw.Write(peSec.Length);
                            sw.Write(peSec.Name);
                            sw.Write(peSec.Protect);
                            sw.Write(peSec.State);
                            sw.Write(peSec.Type);
                            sw.Write(peSec.Data);
                        }
                    }
                    else
                    {
                        sw.Write((int)0);
                    }
                    //Heaps
                    sw.Write("HEAPS");
                    if (Heaps != null)
                    {
                        sw.Write(Heaps.Count);
                        foreach (Heap heap in Heaps)
                        {
                            sw.Write(heap.Base.ToInt32());
                            sw.Write(heap.Flag);
                            sw.Write(heap.Length);
                            sw.Write(heap.Protect);
                            sw.Write(heap.State);
                            sw.Write(heap.Type);
                            sw.Write(heap.Data);
                        }
                    }
                    else
                    {
                        sw.Write((int)0);
                    }
                }
                return true;
            }
            catch(Exception e)
            {
                string strMsg = "保存文件时出错!\r\n错误详情:\r\n";
                strMsg += e.Message;
                MessageBox.Show(strMsg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
    }
}
